home *** CD-ROM | disk | FTP | other *** search
/ Isometric Game Programming with DirectX 7.0 / Isometric Game Programming.iso / source / chapter21 / isohex21_1 / isohex21_1.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-28  |  12.8 KB  |  500 lines

  1. /*****************************************************************************
  2. IsoHex21_1.cpp
  3. Ernest S. Pazera
  4. 09SEPT2000
  5. Start a WIN32 Application Workspace, add in this file
  6. Requires the following libs:
  7. ddraw.lib, dxguid.lib
  8. Requires the following files:
  9. DDFuncs.h.cpp, GDICanvas.h/cpp, IsoMouseMap.h/cpp,
  10. IsoScroller.h/cpp, IsoTilePlotter.h/cpp, IsoTileWalker.h/cpp
  11. TileSet.h/cpp. IsoHexCore.h, IsoHexDefs.h
  12. IsoRenderer.h/cpp
  13. *****************************************************************************/
  14.  
  15. //////////////////////////////////////////////////////////////////////////////
  16. //INCLUDES
  17. //////////////////////////////////////////////////////////////////////////////
  18. #define WIN32_LEAN_AND_MEAN  
  19.  
  20. #include <windows.h>  
  21. #include "DDFuncs.h"
  22. #include "TileSet.h"
  23. #include "IsoHexCore.h"
  24. #include "IsoRenderer.h"
  25. #include <list>
  26.  
  27. //////////////////////////////////////////////////////////////////////////////
  28. //DEFINES
  29. //////////////////////////////////////////////////////////////////////////////
  30. //name for our window class
  31. #define WINDOWCLASS "ISOHEX21"
  32. //title of the application
  33. #define WINDOWTITLE "IsoHex 21-1"
  34.  
  35. const int MAPWIDTH=40;
  36. const int MAPHEIGHT=40;
  37.  
  38. const int SCREENWIDTH=640;
  39. const int SCREENHEIGHT=480;
  40.  
  41. const int UPPERLEFT=0;
  42. const int UPPERRIGHT=1;
  43. const int LOWERRIGHT=2;
  44. const int LOWERLEFT=3;
  45.  
  46. //////////////////////////////////////////////////////////////////////////////
  47. //TYPEDEFS/STRUCTS
  48. //////////////////////////////////////////////////////////////////////////////
  49.  
  50. //////////////////////////////////////////////////////////////////////////////
  51. //PROTOTYPES
  52. //////////////////////////////////////////////////////////////////////////////
  53. bool Prog_Init();//game data initalizer
  54. void Prog_Loop();//main game loop
  55. void Prog_Done();//game clean up
  56.  
  57. //////////////////////////////////////////////////////////////////////////////
  58. //GLOBALS
  59. //////////////////////////////////////////////////////////////////////////////
  60. HINSTANCE hInstMain=NULL;//main application handle
  61. HWND hWndMain=NULL;//handle to our main window
  62.  
  63. //directdraw
  64. LPDIRECTDRAW7 lpdd=NULL;
  65. LPDIRECTDRAWSURFACE7 lpddsMain=NULL;
  66. LPDIRECTDRAWSURFACE7 lpddsBack=NULL;
  67. LPDIRECTDRAWSURFACE7 lpddsFrame=NULL;
  68.  
  69. //tilesets
  70. CTileSet tsBack;
  71. CTileSet tsFringe;
  72.  
  73. //isohexcore components
  74. CTilePlotter TilePlotter;//plotter
  75. CTileWalker TileWalker;//walker
  76. CScroller Scroller;//scroller
  77. CMouseMap MouseMap;//mousemap
  78. CRenderer Renderer;//renderer
  79.  
  80. POINT ptScroll;//keep track of how quickly we scroll
  81.  
  82. //map location structure
  83. struct MapLocation
  84. {
  85.     bool bLand;
  86.     int iFringe[4];
  87. };
  88.  
  89. MapLocation mlMap[MAPWIDTH][MAPHEIGHT];//map array
  90.  
  91. //fringe lookup table
  92. int FringeLookUp[8]={-1,0,1,1,2,3,1,1};
  93.  
  94. //rendering functionprototype
  95. void RenderFunc(LPDIRECTDRAWSURFACE7 lpddsDst,RECT* rcClip,int xDst,int yDst,int xMap,int yMap);
  96. void CalcFringe();//calculate entire map
  97. void CalcFringe(int x,int y);//calculate for individual map location
  98. void CalcFringeNeighborhood(int x,int y);//calculate for a tile neighborhood
  99.  
  100. //////////////////////////////////////////////////////////////////////////////
  101. //WINDOWPROC
  102. //////////////////////////////////////////////////////////////////////////////
  103. LRESULT CALLBACK TheWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
  104. {
  105.     //which message did we get?
  106.     switch(uMsg)
  107.     {
  108.     case WM_KEYDOWN:
  109.         {
  110.             switch(wParam)
  111.             {
  112.             case VK_ESCAPE:
  113.                 {
  114.                     DestroyWindow(hWndMain);
  115.                     return(0);
  116.                 }break;
  117.             }
  118.         }break;
  119.     case WM_DESTROY://the window is being destroyed
  120.         {
  121.  
  122.             //tell the application we are quitting
  123.             PostQuitMessage(0);
  124.  
  125.             //handled message, so return 0
  126.             return(0);
  127.  
  128.         }break;
  129.     case WM_PAINT://the window needs repainting
  130.         {
  131.             //a variable needed for painting information
  132.             PAINTSTRUCT ps;
  133.             
  134.             //start painting
  135.             HDC hdc=BeginPaint(hwnd,&ps);
  136.  
  137.             /////////////////////////////
  138.             //painting code would go here
  139.             /////////////////////////////
  140.  
  141.             //end painting
  142.             EndPaint(hwnd,&ps);
  143.                         
  144.             //handled message, so return 0
  145.             return(0);
  146.         }break;
  147.     }
  148.  
  149.     //pass along any other message to default message handler
  150.     return(DefWindowProc(hwnd,uMsg,wParam,lParam));
  151. }
  152.  
  153.  
  154. //////////////////////////////////////////////////////////////////////////////
  155. //WINMAIN
  156. //////////////////////////////////////////////////////////////////////////////
  157. int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
  158. {
  159.     //assign instance to global variable
  160.     hInstMain=hInstance;
  161.  
  162.     //create window class
  163.     WNDCLASSEX wcx;
  164.  
  165.     //set the size of the structure
  166.     wcx.cbSize=sizeof(WNDCLASSEX);
  167.  
  168.     //class style
  169.     wcx.style=CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  170.  
  171.     //window procedure
  172.     wcx.lpfnWndProc=TheWindowProc;
  173.  
  174.     //class extra
  175.     wcx.cbClsExtra=0;
  176.  
  177.     //window extra
  178.     wcx.cbWndExtra=0;
  179.  
  180.     //application handle
  181.     wcx.hInstance=hInstMain;
  182.  
  183.     //icon
  184.     wcx.hIcon=LoadIcon(NULL,IDI_APPLICATION);
  185.  
  186.     //cursor
  187.     wcx.hCursor=LoadCursor(NULL,IDC_ARROW);
  188.  
  189.     //background color
  190.     wcx.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
  191.  
  192.     //menu
  193.     wcx.lpszMenuName=NULL;
  194.  
  195.     //class name
  196.     wcx.lpszClassName=WINDOWCLASS;
  197.  
  198.     //small icon
  199.     wcx.hIconSm=NULL;
  200.  
  201.     //register the window class, return 0 if not successful
  202.     if(!RegisterClassEx(&wcx)) return(0);
  203.  
  204.     //create main window
  205.     hWndMain=CreateWindowEx(0,WINDOWCLASS,WINDOWTITLE, WS_POPUP | WS_VISIBLE,0,0,320,240,NULL,NULL,hInstMain,NULL);
  206.  
  207.     //error check
  208.     if(!hWndMain) return(0);
  209.  
  210.     //if program initialization failed, then return with 0
  211.     if(!Prog_Init()) return(0);
  212.  
  213.     //message structure
  214.     MSG msg;
  215.  
  216.     //message pump
  217.     for(;;)    
  218.     {
  219.         //look for a message
  220.         if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  221.         {
  222.             //there is a message
  223.  
  224.             //check that we arent quitting
  225.             if(msg.message==WM_QUIT) break;
  226.             
  227.             //translate message
  228.             TranslateMessage(&msg);
  229.  
  230.             //dispatch message
  231.             DispatchMessage(&msg);
  232.         }
  233.  
  234.         //run main game loop
  235.         Prog_Loop();
  236.     }
  237.     
  238.     //clean up program data
  239.     Prog_Done();
  240.  
  241.     //return the wparam from the WM_QUIT message
  242.     return(msg.wParam);
  243. }
  244.  
  245. //////////////////////////////////////////////////////////////////////////////
  246. //INITIALIZATION
  247. //////////////////////////////////////////////////////////////////////////////
  248. bool Prog_Init()
  249. {
  250.     //create IDirectDraw object
  251.     lpdd=LPDD_Create(hWndMain,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT);
  252.  
  253.     //set display mode
  254.     lpdd->SetDisplayMode(SCREENWIDTH,SCREENHEIGHT,16,0,0);
  255.  
  256.     //create primary surface
  257.     lpddsMain=LPDDS_CreatePrimary(lpdd,1);
  258.  
  259.     //get back buffer
  260.     lpddsBack=LPDDS_GetSecondary(lpddsMain);
  261.  
  262.     //create the frame buffer
  263.     lpddsFrame=LPDDS_CreateOffscreen(lpdd,640,480);
  264.  
  265.     //load in the mousemap
  266.     MouseMap.Load("MouseMap.bmp");
  267.  
  268.     //set up the tile plotter
  269.     TilePlotter.SetMapType(ISOMAP_DIAMOND);//diamond mode
  270.     TilePlotter.SetTileSize(MouseMap.GetWidth(),MouseMap.GetHeight());//grab width and height from mousemap
  271.  
  272.     //set up tile walker to diamond mode
  273.     TileWalker.SetMapType(ISOMAP_DIAMOND);
  274.  
  275.     //set up screeen space
  276.     RECT rcTemp;
  277.     SetRect(&rcTemp,0,0,640,480);
  278.     Scroller.SetScreenSpace(&rcTemp);
  279.  
  280.     //load in tiles and cursor
  281.     tsBack.Load(lpdd,"backgroundts.bmp");
  282.     tsFringe.Load(lpdd,"coastlinets.bmp");
  283.  
  284.     //grab tile extent from tileset
  285.     CopyRect(&rcTemp,&tsBack.GetTileList()[0].rcDstExt);
  286.  
  287.     //calculate the worldspace
  288.     Scroller.CalcWorldSpace(&TilePlotter,&rcTemp,MAPWIDTH,MAPHEIGHT);
  289.  
  290.     //calculate the mousemap reference point
  291.     MouseMap.CalcReferencePoint(&TilePlotter,&rcTemp);
  292.  
  293.     //calculate anchor space
  294.     Scroller.CalcAnchorSpace();
  295.  
  296.     //set wrap modes for scroller
  297.     Scroller.SetHWrapMode(WRAPMODE_CLIP);
  298.     Scroller.SetVWrapMode(WRAPMODE_CLIP);
  299.  
  300.     //set scroller anchor to (0,0)
  301.     Scroller.GetAnchor()->x=0;
  302.     Scroller.GetAnchor()->y=0;
  303.  
  304.     //attach scrolelr and tilewalker to mousemap
  305.     MouseMap.SetScroller(&Scroller);
  306.     MouseMap.SetTileWalker(&TileWalker);
  307.  
  308.     //set up the map to a random tilefield
  309.     int x;
  310.     int y;
  311.     for(x=0;x<MAPWIDTH;x++)
  312.     {
  313.         for(y=0;y<MAPHEIGHT;y++)
  314.         {
  315.             if(rand()&1)
  316.             {
  317.                 mlMap[x][y].bLand=true;
  318.             }
  319.             else
  320.             {
  321.                 mlMap[x][y].bLand=false;
  322.             }
  323.         }
  324.     }
  325.  
  326.     //calculate the fringe
  327.     CalcFringe();
  328.  
  329.     //calculate the extent rect
  330.     RECT rcExtent;
  331.     CopyRect(&rcExtent,&tsBack.GetTileList()[0].rcDstExt);//set to background extent
  332.  
  333.     //set up the renderer
  334.     Renderer.SetBackBuffer(lpddsBack);
  335.     Renderer.SetExtentRect(&rcExtent);
  336.     Renderer.SetFrameBuffer(lpddsFrame);
  337.     Renderer.SetMapSize(MAPWIDTH,MAPHEIGHT);
  338.     Renderer.SetMouseMap(&MouseMap);
  339.     Renderer.SetPlotter(&TilePlotter);
  340.     Renderer.SetRenderFunction(RenderFunc);
  341.     Renderer.SetScroller(&Scroller);
  342.     Renderer.SetUpdateRectCount(100);
  343.     Renderer.SetWalker(&TileWalker);
  344.  
  345.     //update the entire screenspace
  346.     Renderer.AddRect(Scroller.GetScreenSpace());
  347.  
  348.     return(true);//return success
  349. }
  350.  
  351. //////////////////////////////////////////////////////////////////////////////
  352. //CLEANUP
  353. //////////////////////////////////////////////////////////////////////////////
  354. void Prog_Done()
  355. {
  356.     //release frame buffer
  357.     LPDDS_Release(&lpddsFrame);
  358.  
  359.     //release main/back surfaces
  360.     LPDDS_Release(&lpddsMain);
  361.  
  362.     //release directdraw
  363.     LPDD_Release(&lpdd);
  364. }
  365.  
  366. //////////////////////////////////////////////////////////////////////////////
  367. //MAIN GAME LOOP
  368. //////////////////////////////////////////////////////////////////////////////
  369. void Prog_Loop()
  370. {
  371.     //grab mouse position
  372.     POINT ptMouse;
  373.     GetCursorPos(&ptMouse);
  374.  
  375.     //calc scrolling
  376.     //horizontal
  377.     ptScroll.x=0;
  378.     if(ptMouse.x<8) ptScroll.x=ptMouse.x-8;
  379.     if(ptMouse.x>SCREENWIDTH-8) ptScroll.x=ptMouse.x-(SCREENWIDTH-8);
  380.     //vertical
  381.     ptScroll.y=0;
  382.     if(ptMouse.y<8) ptScroll.y=ptMouse.y-8;
  383.     if(ptMouse.y>SCREENHEIGHT-8) ptScroll.y=ptMouse.y-(SCREENHEIGHT-8);
  384.  
  385.     //scroll the frame by ptScroll
  386.     Renderer.ScrollFrame(ptScroll.x,ptScroll.y);
  387.     //update the frame
  388.     Renderer.UpdateFrame();
  389.     //flip to show the back buffer
  390.     lpddsMain->Flip(0,DDFLIP_WAIT);
  391. }
  392.  
  393. void RenderFunc(LPDIRECTDRAWSURFACE7 lpddsDst,RECT* rcClip,int xDst,int yDst,int xMap,int yMap)
  394. {
  395.     //check land or sea
  396.     if(mlMap[xMap][yMap].bLand)
  397.     {
  398.         //land
  399.         tsBack.ClipTile(lpddsDst,rcClip,xDst,yDst,0);
  400.     }
  401.     else
  402.     {
  403.         //sea
  404.         tsBack.ClipTile(lpddsDst,rcClip,xDst,yDst,1);
  405.         //upper left zone
  406.         if(FringeLookUp[mlMap[xMap][yMap].iFringe[UPPERLEFT]]>=0)
  407.             tsFringe.ClipTile(lpddsDst,rcClip,xDst,yDst,FringeLookUp[mlMap[xMap][yMap].iFringe[UPPERLEFT]]);
  408.         //upper right zone
  409.         if(FringeLookUp[mlMap[xMap][yMap].iFringe[UPPERRIGHT]]>=0)
  410.             tsFringe.ClipTile(lpddsDst,rcClip,xDst,yDst,FringeLookUp[mlMap[xMap][yMap].iFringe[UPPERRIGHT]]+4);
  411.         //lower right zone
  412.         if(FringeLookUp[mlMap[xMap][yMap].iFringe[LOWERRIGHT]]>=0)
  413.             tsFringe.ClipTile(lpddsDst,rcClip,xDst,yDst,FringeLookUp[mlMap[xMap][yMap].iFringe[LOWERRIGHT]]+8);
  414.         //lower left zone
  415.         if(FringeLookUp[mlMap[xMap][yMap].iFringe[LOWERLEFT]]>=0)
  416.             tsFringe.ClipTile(lpddsDst,rcClip,xDst,yDst,FringeLookUp[mlMap[xMap][yMap].iFringe[LOWERLEFT]]+12);
  417.     }
  418. }
  419.  
  420. void CalcFringe()
  421. {
  422.     //loop through x
  423.     for(int x=0;x<MAPWIDTH;x++)
  424.     {
  425.         //loop through y
  426.         for(int y=0;y<MAPHEIGHT;y++)
  427.         {
  428.             //calc the fringe
  429.             CalcFringe(x,y);
  430.         }
  431.     }
  432. }
  433.  
  434. void CalcFringe(int x,int y)//calculate for individual map location
  435. {
  436.     //range checking
  437.     if(x<0) return;
  438.     if(y<0) return;
  439.     if(x>=MAPWIDTH) return;
  440.     if(y>=MAPHEIGHT) return;
  441.     //calculate the tile neighborhood
  442.     bool Neighbor[8];
  443.     //store starting point
  444.     POINT ptStart;
  445.     ptStart.x=x;
  446.     ptStart.y=y;
  447.     //next map location
  448.     POINT ptNext;
  449.     for(int dir=0;dir<8;dir++)
  450.     {
  451.         //walk to neighbor
  452.         ptNext=TileWalker.TileWalk(ptStart,(ISODIRECTION)dir);
  453.         //range check 
  454.         if(ptNext.x<0 || ptNext.y<0 || ptNext.x>=MAPWIDTH || ptNext.y>=MAPHEIGHT)
  455.         {
  456.             //out of bounds
  457.             Neighbor[dir]=0;
  458.         }
  459.         else
  460.         {
  461.             //check map location
  462.             if(mlMap[ptNext.x][ptNext.y].bLand)
  463.             {
  464.                 //land
  465.                 Neighbor[dir]=1;
  466.             }
  467.             else
  468.             {
  469.                 //water
  470.                 Neighbor[dir]=0;
  471.             }
  472.         }
  473.     }
  474.     //determine zones
  475.     mlMap[ptStart.x][ptStart.y].iFringe[UPPERLEFT]=(Neighbor[6]+2*Neighbor[7]+4*Neighbor[0])|(Neighbor[5]+4*Neighbor[1]);
  476.     mlMap[ptStart.x][ptStart.y].iFringe[UPPERRIGHT]=(Neighbor[0]+2*Neighbor[1]+4*Neighbor[2])|(Neighbor[7]+4*Neighbor[3]);
  477.     mlMap[ptStart.x][ptStart.y].iFringe[LOWERRIGHT]=(Neighbor[2]+2*Neighbor[3]+4*Neighbor[4])|(Neighbor[1]+4*Neighbor[5]);
  478.     mlMap[ptStart.x][ptStart.y].iFringe[LOWERLEFT]=(Neighbor[4]+2*Neighbor[5]+4*Neighbor[6])|(Neighbor[3]+4*Neighbor[7]);
  479. }
  480.  
  481. void CalcFringeNeighborhood(int x,int y)//calculate for a tile neighborhood
  482. {
  483.     //send tile(x,y) to calculate fringe function
  484.     CalcFringe(x,y);
  485.     //store center point
  486.     POINT ptCenter;
  487.     ptCenter.x=x;
  488.     ptCenter.y=y;
  489.     POINT ptNeighbor;
  490.     //loop through directions
  491.     for(int dir=0;dir<8;dir++)
  492.     {
  493.         //determine neighbor
  494.         ptNeighbor=TileWalker.TileWalk(ptCenter,(ISODIRECTION)dir);
  495.         //send neighbor to calculation function
  496.         CalcFringe(ptNeighbor.x,ptNeighbor.y);
  497.     }
  498. }
  499.  
  500.